#include <X11/Xlib.h>
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <X11/Xutil.h>
#include <fstream>
#include <unistd.h>
#include <vector>
#include <string.h>
#include <csignal>
#include <thread>
#include <X11/extensions/XTest.h>
#include "IniFileParser.h"
#include "RemoteDesktopServer.h"
#include "common.h"
#include <memory>

// 信号处理的全局标志
volatile sig_atomic_t shutdown_requested = 0;

// 信号处理函数
void signal_handler(int signum)
{
    std::cout << "捕获到信号 " << signum << std::endl;
    shutdown_requested = 1;
}

RemoteDesktopServer::RemoteDesktopServer(unsigned short display_port, unsigned short controller_port) : display(nullptr), display_server_fd(-1), controller_server_fd(-1), ximage(nullptr)
{
    this->display_port = display_port;
    this->controller_port = controller_port;
    // 初始化X11
    display = XOpenDisplay(NULL);
    if (!display)
    {
        std::cerr << "Cannot open display" << std::endl;
    }
    initDisplayServer();
    initControllerServer();
}

RemoteDesktopServer::~RemoteDesktopServer()
{
    // 清理资源
    if (ximage)
    {
        XDestroyImage(ximage);
    }
    if (display)
    {
        XCloseDisplay(display);
    }
    if (display_server_fd != -1)
    {
        close(display_server_fd);
    }
    if (controller_server_fd != -1)
    {
        close(controller_server_fd);
    }
}

bool RemoteDesktopServer::initDisplayServer()
{
    // 创建TCP服务器
    display_server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (display_server_fd < 0)
    {
        std::cerr << "Failed to create socket" << std::endl;
        return false;
    }

    // 绑定和监听
    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(display_port);
    if (bind(display_server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        std::cerr << "Failed to bind" << std::endl;
        return false;
    }
    if (listen(display_server_fd, 5) < 0)
    { // 监听，最大连接数设为5
        std::cerr << "Listen failed" << std::endl;
        return false;
    }
    return true;
}
bool RemoteDesktopServer::initControllerServer()
{
    // 创建TCP服务器
    controller_server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (controller_server_fd < 0)
    {
        std::cerr << "Failed to create socket" << std::endl;
        return false;
    }

    // 绑定和监听
    struct sockaddr_in address;
    memset(&address, 0, sizeof(address));

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(controller_port);
    if (bind(controller_server_fd, (struct sockaddr *)&address, sizeof(address)) < 0)
    {
        std::cerr << "Failed to bind" << std::endl;
        return false;
    }
    if (listen(controller_server_fd, 5) < 0)
    { // 监听，最大连接数设为5
        std::cerr << "Listen failed" << std::endl;
        return false;
    }
    return true;
}
void RemoteDesktopServer::runDisplay()
{
    // 接受连接
    struct sockaddr_in client_addr;
    socklen_t sin_size = sizeof(struct sockaddr_in);
    // std::cout << "Waiting for connection on port " << display_port << std::endl;

    int new_socket = accept(display_server_fd, (struct sockaddr *)&client_addr, &sin_size);
    if (new_socket < 0)
    {
        std::cerr << "Failed to accept connection" << std::endl;
        return;
    }
    // std::cout << "Accepted new connection from " << inet_ntoa(client_addr.sin_addr) << ": " << client_addr.sin_port << std::endl;

    // 捕获桌面图像
    int screen = DefaultScreen(display);
    ximage = XGetImage(display, RootWindow(display, screen), 0, 0,
                       WidthOfScreen(ScreenOfDisplay(display, screen)),
                       HeightOfScreen(ScreenOfDisplay(display, screen)),
                       AllPlanes, ZPixmap);
    if (!ximage)
    {
        std::cerr << "Failed to create image" << std::endl;
        return;
    }
    ImageInfo ii;
    ii.width = ximage->width;
    ii.height = ximage->height;
    ii.bits_per_pixel = ximage->bits_per_pixel / 8;

    // std::cout << "width: " << ii.width << " height: " << ii.height << " bits_per_pixel: " << ii.bits_per_pixel << std::endl;
    std::vector<char> buffer = serializeImage(ximage); // 将XImage序列化为字节数组

    // 清理资源
    XDestroyImage(ximage);

    size_t image_size = buffer.size(); // 获取图像数据大小

    // std::cout << "Sending image data to client: " << image_size << ", " << buffer.data() << std::endl;

    // 发送图像数据到客户端
    if (net_tools.dispatch(new_socket, (const char *)&ii, sizeof(ii), 0) < 0)
    {
        std::cerr << "dispatch image size failed" << std::endl;
        close(new_socket);
        return;
    }
    if (net_tools.dispatch(new_socket, buffer.data(), buffer.size(), 0) < 0)
    {
        std::cerr << "dispatch image data failed" << std::endl;
        close(new_socket);
        return;
    }
    // 清理资源
    close(new_socket);
}
void *RemoteDesktopServer::startDisplay(void *arg)
{
    RemoteDesktopServer *instance = static_cast<RemoteDesktopServer *>(arg);

    std::cout << "Display thread starting" << std::endl;

    // while (!instance->signal_wraper.isShutdownRequested())
    while (0 == shutdown_requested)
    {
        instance->runDisplay();
    }
    std::cout << "Display thread exiting" << std::endl;
    return NULL;
}

void RemoteDesktopServer::simulateKeyPress(KeySym key, bool press)
{
    std::cout << "Received event: (" << key << ", " << press << ")" << std::endl;
    if (press)
    {
        XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), True, CurrentTime);
        // XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), False, CurrentTime);
    }
    else
    {
        XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), False, CurrentTime);
    }
    XFlush(display);
}

void RemoteDesktopServer::simulateMouseClick(int button, int x, int y, bool press)
{
    std::cout << "Received event: (" << button << ", " << x << ", " << y << ", " << press << ")" << std::endl;

    XTestFakeMotionEvent(display, DefaultScreen(display), x, y, CurrentTime);
    XFlush(display);

    if (press)
    {
        XTestFakeButtonEvent(display, button, True, CurrentTime);
        // XTestFakeButtonEvent(display, button, False, CurrentTime);
    }
    else
    {
        XTestFakeButtonEvent(display, button, False, CurrentTime);
    }
    XFlush(display);
}

void RemoteDesktopServer::simulateMouseMotion(int x, int y)
{
    std::cout << "Received event: (" << x << ", " << y << ")" << std::endl;

    XTestFakeMotionEvent(display, DefaultScreen(display), x, y, CurrentTime + 2);

    XFlush(display);
}

void RemoteDesktopServer::runFakeController()
{
    // 创建并绑定套接字
    struct sockaddr_in client_addr;
    socklen_t sin_size = sizeof(struct sockaddr_in);

    int new_socket = accept(controller_server_fd, (struct sockaddr *)&client_addr, &sin_size);
    if (new_socket < 0)
    {
        std::cerr << "Failed to accept connection. errno: " << errno << std::endl;
        return;
    }
    // std::cout << "Accepted new connection from " << inet_ntoa(client_addr.sin_addr) << ": " << client_addr.sin_port << std::endl;

    XEvent event;

    if (net_tools.receive(new_socket, (char *)&event, sizeof(event), 0) < 0)
    {
        std::cerr << "recv failed" << std::endl;
        close(new_socket);

        return;
    }
    close(new_socket);
    std::cout << "Received event: " << event.type << std::endl;

    // 处理事件
    switch (event.type)
    {
    case KeyPress:
    case KeyRelease:
        // simulateKeyPress(XLookupKeysym(&event.xkey, 0), KeyPress == event.type ? True : False);
        break;
    case ButtonPress:
    case ButtonRelease:
        // simulateMouseClick(event.xbutton.button, event.xbutton.x, event.xbutton.y, KeyPress == event.type ? True : False);
        break;
    case MotionNotify:
        // simulateMouseMotion(event.xmotion.x, event.xmotion.y);
        break;
    default:
        std::cerr << "Unknown event type" << std::endl;
        break;
    }
}
void *RemoteDesktopServer::startFakeController(void *arg)
{
    RemoteDesktopServer *instance = static_cast<RemoteDesktopServer *>(arg);

    std::cout << "FakeController thread starting" << std::endl;

    // while (!instance->signal_wraper.isShutdownRequested())
    while (0 == shutdown_requested)
    {
        instance->runFakeController();
    }
    std::cout << "FakeController thread exit." << std::endl;
    return NULL;
}
void RemoteDesktopServer::start()
{
    // 创建桌面显示线程
    if (pthread_create(&display_thread, NULL, &RemoteDesktopServer::startDisplay, this) != 0)
    {
        std::cerr << "display_thread create Failed" << std::endl;
        return;
    }

    // 创建处理鼠标键盘事件线程
    if (pthread_create(&event_thread, NULL, &RemoteDesktopServer::startFakeController, this) != 0)
    {
        std::cerr << "event_thread create Failed" << std::endl;
        return;
    }
    pthread_join(display_thread, NULL);
    pthread_join(event_thread, NULL);
    std::cout << "server thread exit." << std::endl;
    return;
}
// 序列化XImage到字节流
std::vector<char> RemoteDesktopServer::serializeImage(const XImage *ximage)
{
    std::vector<char> buffer; /* image data */
    buffer.clear();
    if (!ximage)
    {
        std::cerr << "image is null ptr." << std::endl;
        return buffer;
    }
    // 获取图像的宽度和高度
    int width = ximage->width;
    int height = ximage->height;

    // 计算每个像素的字节数，这里假设是24位颜色深度
    int bytes_per_pixel = ximage->bits_per_pixel / 8;

    // 计算整个图像的字节数
    size_t image_size = width * height * bytes_per_pixel;

    // 调整buffer大小
    buffer.resize(image_size);

    // 复制图像数据到buffer
    memcpy(buffer.data(), ximage->data, buffer.size());
    return buffer;
}

int main()
{
    uint16_t usDisplayPort, usControllerPort;

    signal(SIGINT, signal_handler); // 注册信号处理函数

    // IniFileParser ini_parser("../config.ini");
    std::shared_ptr<IniFileParser> iniParserPtr = std::make_shared<IniFileParser>("../config.ini");

    int port;
    if (!iniParserPtr->getIntValue("display port", port))
    {
        return EXIT_FAILURE;
    }
    if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    {
        std::cerr << "Invalid port number " << port << std::endl;
        return EXIT_FAILURE;
    }
    else if (port > 0 && port < 1024) // 知名端口，通常被IANA（互联网号码分配机构）分配给一些公认的服务
    {
        std::cerr << "port number " << port << " is not available." << std::endl;
        return EXIT_FAILURE;
    }
    else
    {
        usDisplayPort = static_cast<uint16_t>(port);
    }
    std::cout << "display port: " << usDisplayPort << std::endl;
    if (!iniParserPtr->getIntValue("controller port", port))
    {
        return EXIT_FAILURE;
    }
    if (port < 0 || port > std::numeric_limits<uint16_t>::max())
    {
        std::cerr << "Invalid port number " << port << std::endl;
        return EXIT_FAILURE;
    }
    else if (port > 0 && port < 1024) // 知名端口，通常被IANA（互联网号码分配机构）分配给一些公认的服务
    {
        std::cerr << "port number " << port << " is not available." << std::endl;
        return EXIT_FAILURE;
    }
    else
    {
        usControllerPort = static_cast<uint16_t>(port);
    }
    std::cout << "controller port: " << usControllerPort << std::endl;

    RemoteDesktopServer server(usDisplayPort, usControllerPort);
    server.start();

    return EXIT_SUCCESS;
}